package org.maxgroundstation.groundstation.view.map;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.TimeZone;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

import org.maxgroundstation.groundstation.GroundStation;
import org.maxgroundstation.groundstation.comm.service.gps.GpsService;
import org.maxgroundstation.groundstation.comm.service.gps.PointOfInterest;

/**
 * A dialog for displaying point of interest data.
 * @author Scott Davis
 * 
 * Copyright (C) 2010  Scott Davis
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@SuppressWarnings("serial")
public class PointOfInterestDialog extends JDialog {

    // Static members.
    private static final String POI_DIR = System.getProperty("user.home") + File.separator + 
            "max_groundstation" + File.separator + "poi";
    
    // Data members
    private PointOfInterest poi;
    private GroundStation gs;
    private DecimalFormat positionFormatter;
    private DateFormat dateFormatter;
    private JTextField nameTF;
    private JTextArea descriptionTA;
    
    /**
     * Constructor.
     * @param owner the JFrame dialog owner.
     * @param poi the point of interest.
     * @param gs the ground station.
     */
    public PointOfInterestDialog(JFrame owner, PointOfInterest poi, GroundStation gs) {
        // User JDialog constructor.
        super(owner, poi.getName(), false);
        
        // Initialize data members.
        this.poi = poi;
        this.gs = gs;
        positionFormatter = new DecimalFormat("0.000000");
        dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz");
        dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
        
        // Set the layout.
        setLayout(new BorderLayout());
        
        // Create the top panel.
        JPanel topPanel = new JPanel(new BorderLayout(0, 0));
        add(topPanel, BorderLayout.NORTH);
        
        // Create the image panel.
        JPanel imagePanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        topPanel.add(imagePanel, BorderLayout.CENTER);
        
        // Display each video snapshot scaled down.
        Iterator<String> i = poi.getSnapshotFileNames().iterator();
        while (i.hasNext()) {
            String imageName = i.next();
            Icon imageIcon = createScaledImageIcon(imageName);
            JLabel imageLabel = new JLabel(imageIcon);
            imagePanel.add(imageLabel);
        }
        
        // Create the info panel.
        JPanel infoPanel = new JPanel(new GridLayout(3, 1));
        topPanel.add(infoPanel, BorderLayout.SOUTH);
        
        // Create the latitude panel.
        JPanel latitudePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        infoPanel.add(latitudePanel);
        
        // Create the latitude label.
        JLabel latitudeLabel = new JLabel("Latitude: " + positionFormatter.format(poi.getLatitude()));
        latitudePanel.add(latitudeLabel);
        
        // Create the longitude panel.
        JPanel longitudePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        infoPanel.add(longitudePanel);
        
        // Create the longitude label.
        JLabel longitudeLabel = new JLabel("Longitude: " + positionFormatter.format(poi.getLongitude()));
        longitudePanel.add(longitudeLabel);
        
        // Create the time stamp panel.
        JPanel timestampPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        infoPanel.add(timestampPanel);
        
        // Create the time stamp label.
        JLabel timestampLabel = new JLabel("Time: " + dateFormatter.format(poi.getTimestamp()));
        timestampPanel.add(timestampLabel);
        
        // Create the data panel.
        JPanel dataPanel = new JPanel(new BorderLayout());
        add(dataPanel, BorderLayout.CENTER);
        
        // Create the name panel.
        JPanel namePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        dataPanel.add(namePanel, BorderLayout.NORTH);
        
        // Create the name label.
        JLabel nameLabel = new JLabel("Name: ");
        namePanel.add(nameLabel);
        
        // Create the name text field.
        nameTF = new JTextField(25);
        nameTF.setText(poi.getName());
        namePanel.add(nameTF);
        
        // Create the description panel.
        JPanel descriptionPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        descriptionPanel.setBorder(new TitledBorder("Description"));
        dataPanel.add(descriptionPanel, BorderLayout.CENTER);
        
        // Create the description text area.
        descriptionTA = new JTextArea("", 10, 30);
        descriptionTA.setText(poi.getDescription());
        descriptionPanel.add(descriptionTA);
        
        // Create the button panel.
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        add(buttonPanel, BorderLayout.SOUTH);
        
        // Create the edit button.
        JButton editButton = new JButton("Save Edits");
        editButton.setToolTipText("Save any name or description changes.");
        editButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                editPoi();
            }
        });
        buttonPanel.add(editButton);
        
        // Create the delete button.
        JButton deleteButton = new JButton("Delete");
        deleteButton.setToolTipText("Delete the point of interest.");
        deleteButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                deletePoi();
            }
        });
        buttonPanel.add(deleteButton);
        
        // Create the close button.
        JButton cancelButton = new JButton("Close");
        cancelButton.setToolTipText("Close the dialog.");
        cancelButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        });
        buttonPanel.add(cancelButton);
        
        // Pack the dialog.
        pack();
        
        // Set the location of the dialog.
        int xPos = owner.getX() + (owner.getWidth() / 2) - (getWidth() / 2);
        int yPos = owner.getY() + (owner.getHeight() / 2) - (getHeight() / 2);
        setLocation(new Point(xPos, yPos));
    }
    
    /** 
     * Edits the point of interest.
     */
    private void editPoi() {
        poi.setName(nameTF.getText());
        poi.setDescription(descriptionTA.getText());
        if (hasGpsService()) {
            getGpsService().commitPointOfInterestEdit(poi);
        }
    }
    
    /**
     * Delete the point of interest.
     */
    private void deletePoi() {
        if (hasGpsService()) {
            getGpsService().deletePointOfInterest(poi);
        }
        dispose();
    }
    
    /**
     * Checks if the GPS service exists.
     * @return true if GPS service exists.
     */
    private boolean hasGpsService() {
        return gs.getServiceComm().hasService(GpsService.SERVICE_ID);
    }
    
    /**
     * Gets the GPS service.
     * @return GPS service or null if not available.
     */
    private GpsService getGpsService() {
        GpsService service = null;
        if (hasGpsService()) {
            service = (GpsService) gs.getServiceComm().getService(
                    GpsService.SERVICE_ID);
        }
        return service;
    }
    
    /**
     * Creates a scaled image icon from an image.
     * @param imageFileName the image file name.
     * @return image icon.
     */
    private ImageIcon createScaledImageIcon(String imageFileName) {
        ImageIcon initialImageIcon = new ImageIcon(POI_DIR + File.separator + imageFileName);
        int initialWidth = initialImageIcon.getIconWidth();
        int initialHeight = initialImageIcon.getIconHeight();
        Image initialImage = initialImageIcon.getImage();
        
        float scaleFactor = 1F;
        if (initialWidth > initialHeight) scaleFactor = 100F / (float) initialWidth;
        else scaleFactor = 100F / (float) initialHeight;
        
        int finalWidth = (int) (initialWidth * scaleFactor);
        int finalHeight = (int) (initialHeight * scaleFactor);
        
        BufferedImage dst = new BufferedImage(finalWidth, finalHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = dst.createGraphics();
        g2.drawImage(initialImage, 0, 0, finalWidth, finalHeight, this);
        g2.dispose();
        return new ImageIcon(dst);
    }
}